package com.soxing.braindata.service.manager;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.google.common.collect.Lists;
import com.soxing.braindata.dao.domain.request.SearchRequest;
import com.soxing.braindata.dao.entity.Equipment;
import com.soxing.braindata.dao.entity.Experiment;
import com.soxing.braindata.dao.entity.TesteeExperiment;
import com.soxing.braindata.dao.entity.TesteeExperimentFile;
import com.soxing.braindata.dao.service.IEquipmentService;
import com.soxing.braindata.dao.service.IExperimentService;
import com.soxing.braindata.dao.service.ITesteeExperimentFileService;
import com.soxing.braindata.dao.service.ITesteeExperimentService;
import com.soxing.braindata.domain.request.TesteeExperimentSearchRequest;
import com.soxing.braindata.domain.vo.TesteeExperimentVo;
import com.soxing.braindata.domain.vo.TesteeVisitExperimentVo;
import com.soxing.common.utils.response.WebResponse;
import com.soxing.common.utils.util.ObjectMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author :durango
 * @date :2022/6/11 15:03
 * @description 被试任务管理服务实现
 */
@Service
public class TesteeExperimentManagerImpl extends AbstractManager<TesteeExperiment> implements ITesteeExperimentManager {

    @Resource
    private ITesteeExperimentService testeeExperimentService;
    @Resource
    private ITesteeExperimentFileService testeeExperimentFileService;
    @Resource
    private IExperimentService experimentService;
    @Resource
    private IEquipmentService equipmentService;

    @Override
    public IService<TesteeExperiment> getService() {
        return testeeExperimentService;
    }

    @Override
    public LambdaQueryWrapper<TesteeExperiment> wrapSearchRequest(SearchRequest request) {
        TesteeExperimentSearchRequest searchRequest = (TesteeExperimentSearchRequest) request;
        if (request == null) {
            searchRequest = new TesteeExperimentSearchRequest();
        }
        TesteeExperiment obj = ObjectMapper.map(searchRequest, TesteeExperiment.class);
        LambdaQueryWrapper<TesteeExperiment> queryWrapper = new LambdaQueryWrapper<>(obj);
        return queryWrapper;
    }

    @Override
    public WebResponse<List<TesteeVisitExperimentVo>> getTesteeVisitExperiment(String testeeNo) {
        List<TesteeExperiment> testeeExperimentList = testeeExperimentService.list(new LambdaQueryWrapper<TesteeExperiment>().eq(TesteeExperiment::getTesteeNo, testeeNo));
        if (CollectionUtils.isEmpty(testeeExperimentList)) {
            return WebResponse.success();
        }

        List<TesteeExperimentVo> testeeExperimentVoList = testeeExperiment2TesteeExperimentVo(testeeExperimentList);
        Map<String, List<TesteeExperimentVo>> groupByVpCodeMap = testeeExperimentVoList.stream()
                .collect(Collectors.groupingBy(TesteeExperimentVo::getVpCode));
        TreeMap<String, List<TesteeExperimentVo>> treeMap = new TreeMap<>(groupByVpCodeMap);

        List<TesteeVisitExperimentVo> voList = Lists.newArrayList();
        int i = 0;
        for (Map.Entry<String, List<TesteeExperimentVo>> entry : treeMap.entrySet()) {
            String vpCode = entry.getKey();
            List<TesteeExperimentVo> experimentList = entry.getValue();

            String vpName = calcVpName(vpCode);
            TesteeVisitExperimentVo vo = TesteeVisitExperimentVo.builder().vpCode(vpCode).vpName(vpName)
                    .orderNum(i).testeeExperimentList(experimentList).build();
            voList.add(vo);
        }
        return WebResponse.success(voList);
    }

    /**
     * testeeExperiment->TesteeExperimentVo
     *
     * @param testeeExperimentList
     * @return
     */
    private List<TesteeExperimentVo> testeeExperiment2TesteeExperimentVo(List<TesteeExperiment> testeeExperimentList) {
        Set<Integer> experimentIdSet = new HashSet<>();
        Set<Integer> equipmentIdSet = new HashSet<>();
        Set<Integer> testeeExperimentFileIdSet = new HashSet<>();

        testeeExperimentList.stream().forEach(testeeExperiment -> {
            experimentIdSet.add(testeeExperiment.getExperimentId());
            equipmentIdSet.add(testeeExperiment.getEquipmentId());
            testeeExperimentFileIdSet.add(testeeExperiment.getTesteeExperimentFileId());
        });
        List<Experiment> experimentList = experimentService.list(new LambdaQueryWrapper<Experiment>().in(Experiment::getId, experimentIdSet));
        List<Equipment> equipmentList = equipmentService.list(new LambdaQueryWrapper<Equipment>().in(Equipment::getId, equipmentIdSet));
        List<TesteeExperimentFile> testeeExperimentFileList = testeeExperimentFileService.list(new LambdaQueryWrapper<TesteeExperimentFile>().in(TesteeExperimentFile::getId, testeeExperimentFileIdSet));
        if (experimentList == null) {
            experimentList = new ArrayList<>();
        }
        if (equipmentList == null) {
            equipmentList = new ArrayList<>();
        }
        if (testeeExperimentFileList == null) {
            testeeExperimentFileList = new ArrayList<>();
        }
        Map<Integer, Experiment> experimentMap = experimentList.stream().collect(Collectors.toMap(Experiment::getId, Function.identity(), (n1, n2) -> n1));
        Map<Integer, Equipment> equipmentMap = equipmentList.stream().collect(Collectors.toMap(Equipment::getId, Function.identity(), (n1, n2) -> n1));
        Map<Integer, TesteeExperimentFile> testeeExperimentFileIdMap = testeeExperimentFileList.stream().collect(Collectors.toMap(TesteeExperimentFile::getId, Function.identity(), (n1, n2) -> n1));

        List<TesteeExperimentVo> voList = new ArrayList<>();
        testeeExperimentList.forEach(testeeExperiment -> {
            TesteeExperimentVo vo = new TesteeExperimentVo();
            ObjectMapper.map(testeeExperiment, vo);

            Experiment experiment = experimentMap.get(testeeExperiment.getExperimentId());
            Equipment equipment = equipmentMap.get(testeeExperiment.getEquipmentId());
            TesteeExperimentFile testeeExperimentFile = testeeExperimentFileIdMap.get(testeeExperiment.getTesteeExperimentFileId());

            if (equipment != null) {
                vo.setEquipmentName(equipment.getEquipmentName());
            }
            if (experiment != null) {
                vo.setExperimentName(experiment.getExperimentName());
            }
            if (testeeExperimentFile != null) {
                vo.setTesteeExperimentFileName(testeeExperimentFile.getFileName());
                vo.setTesteeExperimentFilePath(testeeExperimentFile.getFilePath());
                vo.setQa(testeeExperimentFile.getQa());
                vo.setTotalSize(testeeExperimentFile.getTotalSize());
            }
            voList.add(vo);
        });
        return voList;
    }


    /**
     * 基于访视编码计算访视名
     * V0：基线
     * V1:第一次随访
     * V2：第二次随访
     * V2-1: 第二次随访加一次访视
     * 注：在不同随访阶段需要临时增加访视，按V1-1的形式增加访视阶段
     *
     * @param vpCode 访视编码
     * @return 访视名
     */
    private String calcVpName(String vpCode) {
        if (StringUtils.isBlank(vpCode)) {
            return "其他";
        }
        if (vpCode.equalsIgnoreCase("V0")) {
            return "基线";
        }
        String code = vpCode.substring(1);
        String[] strings = code.split("\\-");
        if (strings.length == 1) {
            return "第" + strings[0] + "次随访";
        }
        return "其他";
    }


    //
    private void updateFinishJson()
    {

    }

}

